#include "timer.h"


//*****************************************************************************
// Private Defines + Private Variables
//*****************************************************************************
UINT8_BITS G_bfButtonInput;
UINT8 G_ucCondInput;
UINT8 G_ucaDebCounter[8] = {0,0,0,0,0,0,0,0};
UINT16 G_uiaButtonHoldTime[8] = {0,0,0,0,0,0,0,0};

UINT16 G_uiKeepAliveTimer = 0;


// Init timer 0 for generating interrupt in every ms
void initTimer0(void)
{
    T0CONbits.TMR0ON = 0b0;     // Disable Timer0
    T0CONbits.T0PS = 0b001;     // 1:4 Prescale value
    T0CONbits.PSA = 0b0;        // Prescaler is assigned
	T0CONbits.T0CS = 0b0;       // Clock source is internal instruction cycle
    T0CONbits.T08BIT = 0b0;     // 16-bit timer width
    
    // Init timer register
    TMR0H = (UINT8)(TIMER_RELOAD_VALUE >> 8);
    TMR0L = (UINT8)(TIMER_RELOAD_VALUE & 0xFF);
    
    // Enable interrupt
    INTCONbits.T0IF = 0b0;      // Clear interrupt flag
    INTCONbits.T0IE = 0b1;      // Enable interrupt
    
    G_ucCondInput = 0;
}

void startTimer0(void)
{
    T0CONbits.TMR0ON = 0b1;     // Enable Timer0
}

void stopTimer0(void)
{
    T0CONbits.TMR0ON = 0b0;     // Disable Timer0
}

// Interrupt service routine for timer0
void timer0ISR(void)
{
	UINT8 ucTemp;
	UINT8 ucMask;
	UINT8 ucIndex;

    //dTest_LED = dLED_OFF;    
    
	ucTemp = TMR0L;

	// Reload timer value
	TMR0H = (UINT8)(TIMER_RELOAD_VALUE >> 8);
	TMR0L = (UINT8)(TIMER_RELOAD_VALUE & 0xFF) + ucTemp + 2;

    //Read inputs and assign ButtonInput bits to physical lines
    G_bfButtonInput.Val = PORTA;
    G_bfButtonInput.bits.b6 = dMem1_Pin;
    G_bfButtonInput.bits.b7 = dLocal_Pin;
    
    G_bfButtonInput.Val ^= 0xFF;                // Invert the bits because buttons are pull to gnd when pressed 

    for(ucMask=1, ucIndex=0; ucIndex<8; ++ucIndex)
    {
        if((G_bfButtonInput.Val & ucMask) != (G_ucCondInput & ucMask))              // Was the port changed?
            if(dDebouncingTime != G_ucaDebCounter[ucIndex])                         // Time is over?
                ++G_ucaDebCounter[ucIndex];                                         // Increase the debouncing timer
            else
            {
                G_ucCondInput ^= ucMask;                                            // Toggle state
                G_ucaDebCounter[ucIndex] = 0;                                       // Start the debouncing timer
            }    
        else
            G_ucaDebCounter[ucIndex]=0;                                             // Start the debouncing timer
            
        if(G_ucCondInput & ucMask)
        {                                                                           // Button pressed?
            if(G_uiaButtonHoldTime[ucIndex]<0xffff)
                ++G_uiaButtonHoldTime[ucIndex];                                     // Measure the hold time
            else
                G_uiaButtonHoldTime[ucIndex]=0xffff;                                
        }        
        else 
            G_uiaButtonHoldTime[ucIndex] = 0;                                       // if button released reset hold time measurement
        ucMask<<=1;
    }//for(ucMask=1,    
  
  
    if(G_uiKeepAliveTimer)                                                          // Handle keep alive timer
        --G_uiKeepAliveTimer;
    
    //dTest_LED ^= 0b1;
    //dTest_LED = dLED_ON;

	INTCONbits.T0IF = 0b0;      // Clear interrupt flag	
}
